package org.celery.modules.productSource.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.ocean.rawsdk.ApiExecutor;
import com.alibaba.ocean.rawsdk.client.APIId;
import com.alibaba.ocean.rawsdk.common.SDKResult;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.ConvertUtils;
import org.celery.common.config.AlibabaProperties;
import org.celery.modules.productSource.entity.*;
import org.celery.modules.productSource.mapper.ProductSourceMapper;
import org.celery.modules.productSource.service.IProductSourceService;
import org.celery.modules.productSource.vo.AlibabaProductGetParamVo;
import org.celery.modules.shop.entity.Shop;
import org.celery.modules.shop.service.IShopService;
import org.celery.modules.ticket.entity.Ticket;
import org.celery.modules.ticket.service.ITicketService;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springblade.core.mp.support.Query;

import java.util.*;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Slf4j
public class IProductSourceServiceImpl extends ServiceImpl<ProductSourceMapper, ProductSource> implements IProductSourceService {
    private final IShopService shopService;
    private final AlibabaProperties alibabaProperties;
    private final ITicketService ticketService;
    private static Long shopIdStatic = 1670753159815319553L;
    @Override
    @Async
    public Future<HashMap<String, Object>> getProductSourceServiceByPage(AlibabaProductGetListParam alibabaProductGetListParam, Long shopIdStatic) {
        ApiExecutor apiExecutor = new ApiExecutor(alibabaProperties.getAppKey(), alibabaProperties.getAppSecret());
        AlibabaProductGetListParam param = new AlibabaProductGetListParam();
        param.setOceanApiId(new APIId("com.alibaba.product", "alibaba.product.list.get", 1));
        if(Func.isNotEmpty(alibabaProductGetListParam.getPageNo()) && Func.isNotEmpty(alibabaProductGetListParam.getPageSize())) {
            param.setPageNo(alibabaProductGetListParam.getPageNo());
            param.setPageSize(alibabaProductGetListParam.getPageSize());
        } else {
            throw new ServiceException("PageNo和PageSize参数必传");
        }
        Shop currentShop = getCurrentShop(shopIdStatic);
        SDKResult<AlibabaProductGetListResult> result = apiExecutor.execute(param, currentShop.getAccessToken());
        String errorCode = result.getErrorCode();
        if (Func.isNotEmpty(errorCode) && errorCode.equals("gw.NeedUserAuthenticated")) {
            throw new ServiceException("没有获取数据的权限");
        }
        if(Func.isNotEmpty(result.getResult())) {
            JSONObject pageResult = ((JSONObject) result.getResult().getResult()).getJSONObject("pageResult");
            if(Func.isNull(pageResult)) {
                throw new ServiceException("参数转化异常");
            }
            JSONArray resultList = pageResult.getJSONArray("resultList");
            if(Func.isNull(resultList)) {
                throw new ServiceException("参数转化异常");
            }
            Integer totalRecords = pageResult.getInteger("totalRecords");
            if(Func.isNull(totalRecords)) {
                throw new ServiceException("参数转化异常");
            }
            Integer pageIndex = pageResult.getInteger("pageIndex");
            if(Func.isNull(pageIndex)) {
                throw new ServiceException("参数转化异常");
            }
            Integer pageSize = pageResult.getInteger("sizePerPage");
            if(Func.isNull(pageSize)) {
                throw new ServiceException("参数转化异常");
            }
            HashMap<String, Object> hashMap = new HashMap<String, Object>() {{
                put("resultList", resultList);
                put("totalRecords", totalRecords);
                put("pageIndex", pageIndex);
                put("pageSize", pageSize);
            }};
            return new AsyncResult<>(hashMap);
        }
        return new AsyncResult<>(new HashMap<>());
    }

    @Override
    public AlibabaProductGetResult getProductSourceServiceByPageSelf(AlibabaProductGetParam alibabaProductGetParam) {
        ApiExecutor apiExecutor = new ApiExecutor(alibabaProperties.getAppKey(), alibabaProperties.getAppSecret());
        AlibabaProductGetParam param = new AlibabaProductGetParam();
        param.setOceanApiId(new APIId("com.alibaba.product", "alibaba.product.get", 1));
        if(Func.isNotEmpty(alibabaProductGetParam.getProductID())) {
            param.setProductID(alibabaProductGetParam.getProductID());
        } else {
            throw new ServiceException("ProductID参数必传");
        }
        Shop currentShop = getCurrentShop(shopIdStatic);
        SDKResult<AlibabaProductGetResult> result = apiExecutor.execute(param, currentShop.getAccessToken());
        if(result.getResult() != null) {
            return result.getResult();
        }
        return null;
    }

    public HashMap<String, Object> getCurrentProductSourceServiceByPageSelf(Ticket ticket, Query query) {
        if(Func.isEmpty(query.getCurrent()) || Func.isEmpty(query.getSize())) {
            query.setCurrent(1);
            query.setSize(19);
        }
        IPage<Ticket> page = ticketService.page(Condition.getPage(query), Condition.getQueryWrapper(ticket));
        List<AlibabaProductGetParamVo> collect = page.getRecords().stream().map(ticketObj -> {
            AlibabaProductGetParam alibabaProductGetParam = new AlibabaProductGetParam();
            alibabaProductGetParam.setProductID(ticketObj.getProductId());
            AlibabaProductGetResult productSourceServiceByPageSelf = getProductSourceServiceByPageSelf(alibabaProductGetParam);
            AlibabaProductGetParamVo copy = BeanUtil.copy(productSourceServiceByPageSelf, AlibabaProductGetParamVo.class);
            copy.setTicket(ticketObj);
            return copy;
        }).collect(Collectors.toList());
        if(Func.isEmpty(collect)) {
            throw new ServiceException("参数转化异常");
        }
        return new HashMap<String, Object>() {{
            put("productSourceListByTicket", collect);
            put("total", collect.size());
        }};
    }

    public HashMap<String, Object> getCurrentProductSourceServiceByPageSelfById(String LongId) {
        if(Func.isEmpty(LongId)) {
            throw new ServiceException("请输入商品编号");
        }
        List<Ticket> list = null;
        if(LongId.indexOf(",") != -1) {
            String[] split = LongId.split(",");
            if(Func.isEmpty(split)) {
                throw new ServiceException("请传入正确参数");
            }
            list = ticketService.list(Wrappers.<Ticket>lambdaQuery().in(Ticket::getProductId, ConvertUtils.convert(split, Long.class))
                    .eq(Ticket::getIsDeleted, 0));
        } else {
            list = ticketService.list(Wrappers.<Ticket>lambdaQuery().in(Ticket::getProductId, LongId)
                    .eq(Ticket::getIsDeleted, 0));
        }
        List<AlibabaProductGetParamVo> collect = list.stream().map(ticketObj -> {
            AlibabaProductGetParam alibabaProductGetParam = new AlibabaProductGetParam();
            alibabaProductGetParam.setProductID(ticketObj.getProductId());
            AlibabaProductGetResult productSourceServiceByPageSelf = getProductSourceServiceByPageSelf(alibabaProductGetParam);
            AlibabaProductGetParamVo copy = BeanUtil.copy(productSourceServiceByPageSelf, AlibabaProductGetParamVo.class);
            copy.setTicket(ticketObj);
            return copy;
        }).collect(Collectors.toList());
        if(Func.isEmpty(collect)) {
            throw new ServiceException("参数转化异常");
        }
        return new HashMap<String, Object>() {{
            put("productSourceListByTicket", collect);
            put("total", collect.size());
        }};
    }

    public HashMap<String, Object> getMyCurrentProductSourceServiceByPageSelfById(String LongId, AlibabaProductGetListParam alibabaProductGetListParam, Long  shopIdStatic) {
        ApiExecutor apiExecutor = new ApiExecutor(alibabaProperties.getAppKey(), alibabaProperties.getAppSecret());
        AlibabaProductGetListParam alibabaProductGetParam = new AlibabaProductGetListParam();
        alibabaProductGetParam.setOceanApiId(new APIId("com.alibaba.product", "alibaba.product.list.get", 1));
        Shop currentShop = getCurrentShop(shopIdStatic);
        if(Func.isNotEmpty(LongId)) {
            if(LongId.indexOf(",") != -1) {
                String[] split = LongId.split(",");
                if (Func.isEmpty(split)) {
                    throw new ServiceException("请传入正确参数");
                }
                alibabaProductGetParam.setProductIds((Long[]) ConvertUtils.convert(LongId.split(","), Long.class));
            } else {
                if(Func.isNotEmpty(LongId)) {
                    alibabaProductGetParam.setProductIds(Arrays.asList(Long.valueOf(LongId)).toArray(new Long[0]));
                }
                alibabaProductGetParam.setPageNo(1);
                alibabaProductGetParam.setPageSize(20);
                if(Func.isNotEmpty(alibabaProductGetListParam.getSubjectKey())) {
                    alibabaProductGetParam.setSubjectKey(alibabaProductGetParam.getSubjectKey());
                }
            }
        } else {
            alibabaProductGetParam.setPageNo(1);
            alibabaProductGetParam.setPageSize(20);
            if(Func.isNotEmpty(alibabaProductGetListParam.getSubjectKey())) {
                alibabaProductGetParam.setSubjectKey(alibabaProductGetListParam.getSubjectKey());
            }
        }

        SDKResult<AlibabaProductGetListResult> result = apiExecutor.execute(alibabaProductGetParam, currentShop.getAccessToken());
        String errorCode = result.getErrorCode();
        if (Func.isNotEmpty(errorCode) && errorCode.equals("gw.NeedUserAuthenticated")) {
            throw new ServiceException("没有获取数据的权限");
        }
        if (Func.isNull(result)) {
            throw new ServiceException("参数转化异常");
        }
        AlibabaProductGetListResult result1 = result.getResult();
        if (Func.isNull(result1)) {
            throw new ServiceException("参数转化异常");
        }
        Object resObj = result1.getResult();
        if(Func.isNull(resObj)) {
            throw new ServiceException("参数转化异常");
        }
        Object pageResult = ((JSONObject)resObj).getJSONObject("pageResult");
        if(Func.isNull(pageResult)) {
            throw new ServiceException("参数转化异常");
        }
        JSONArray resultList = ((JSONObject)pageResult).getJSONArray("resultList");
        if(Func.isEmpty(resultList)) {
            throw new ServiceException("参数转化异常");
        }
        Integer totalRecords = ((JSONObject)pageResult).getInteger("totalRecords");
        if(Func.isNull(totalRecords)) {
            throw new ServiceException("参数转化异常");
        }
        Integer pageIndex = ((JSONObject)pageResult).getInteger("pageIndex");
        if(Func.isNull(pageIndex)) {
            throw new ServiceException("参数转化异常");
        }
        Integer pageSize = ((JSONObject)pageResult).getInteger("sizePerPage");
        HashMap<String, Object> hashMap = new HashMap<String, Object>() {{
            put("resultList", resultList);
            put("totalRecords", totalRecords);
            put("pageIndex", pageIndex);
            put("pageSize", pageSize);
        }};
        return hashMap;
    }

    public AlibabaProductGetByIdListResult productSourceServiceByPageSeller(AlibabaProductGetByIdListParam alibabaProductGetByIdListParam, Long shopIdStatic) {
        ApiExecutor apiExecutor = new ApiExecutor(alibabaProperties.getAppKey(), alibabaProperties.getAppSecret());
        AlibabaProductGetByIdListParam param = new AlibabaProductGetByIdListParam();
        param.setOceanApiId(new APIId("com.alibaba.product", "alibaba.product.getByIdList", 1));
        if(Func.isNotEmpty(alibabaProductGetByIdListParam.getProductIdList())) {
            param.setProductIdList(alibabaProductGetByIdListParam.getProductIdList());
        } else {
            throw new ServiceException("productIdList参数必传");
        }
        Shop currentShop = getCurrentShop(shopIdStatic);
        SDKResult<AlibabaProductGetByIdListResult> result = apiExecutor.execute(param, currentShop.getAccessToken());
        if(result.getResult() != null) {
            return result.getResult();
        }
        return null;
    }

    private Shop getCurrentShop(Long shopId) {
        return shopService.getShopById(shopId);
    }

    @Async("taskExecutor")
    @Override
    public Future<Boolean> synchronizeProductSources(Long shopIdStatic) throws ExecutionException, InterruptedException {
        log.info("异步任务===============>");
        long startTime = System.currentTimeMillis();
        AlibabaProductGetListParam alibabaProductGetListParam = new AlibabaProductGetListParam();
        alibabaProductGetListParam.setPageNo(1);
        alibabaProductGetListParam.setPageSize(20);
        Future<HashMap<String, Object>> productSourceServiceByPage = getProductSourceServiceByPage(alibabaProductGetListParam, shopIdStatic);
        HashMap<String, Object> stringObjectHashMap = productSourceServiceByPage.get();
        Integer totalRecords = Integer.valueOf(stringObjectHashMap.get("totalRecords").toString());
        // 需要执行的次数
        Integer totalRecordsPage = ((totalRecords / 20 ) + 1);
        ArrayList<List<ProductSource>> productSourcesList = new ArrayList<>();
        // -----------
        ArrayList<AlibabaProductGetListParam> alibabaProductGetListParams = new ArrayList<>();
        for (int i = 0; i < totalRecordsPage; i++) {
            AlibabaProductGetListParam alibabaProductGetListParamObj = new AlibabaProductGetListParam();
            alibabaProductGetListParamObj.setPageNo(i);
            // 需要重置开始位置
            alibabaProductGetListParamObj.setPageSize(20);
            alibabaProductGetListParams.add(alibabaProductGetListParamObj);
        }
        if(alibabaProductGetListParams.size() > 51) {
            int rollSize = (alibabaProductGetListParams.size() / 51) + 1;
            for (int i = 0; i < rollSize; i++) {
                List<AlibabaProductGetListParam> alibabaProductGetListParamsTemp = alibabaProductGetListParams.stream().skip(i * 51).limit(51).collect(Collectors.toList());
                List<CompletableFuture<Future<HashMap<String, Object>>>> collectList = alibabaProductGetListParamsTemp.stream().map(alibabaProductGetListParamItem ->
                        CompletableFuture.supplyAsync(() ->
                                getProductSourceServiceByPage(alibabaProductGetListParamItem, shopIdStatic))
                ).collect(Collectors.toList());

                CompletableFuture.allOf(collectList.toArray(new CompletableFuture[0])).join();
                if(collectList.size() > 0) {
                    collectList.forEach(item -> {
                        try {
                            HashMap<String, Object> hashMap = item.get().get();
                            if (Func.isNotEmpty(hashMap)) {
                                Object resultList = hashMap.get("resultList");
                                if (Func.isNotEmpty(resultList)) {
                                    List<ProductSource> productSources = JSONArray.parseArray(((JSONArray) resultList).toJSONString(), ProductSource.class);
                                    productSourcesList.add(productSources);
                                }
                            }
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        } catch (ExecutionException e) {
                            throw new RuntimeException(e);
                        }
                    });
                }
            }
        }
        if(Func.isEmpty(productSourcesList)) {
            throw new ServiceException("参数错误");
        }
        List<ProductSource> collect = productSourcesList.stream().flatMap(Collection::stream).collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ProductSource::getProductId))), ArrayList::new));
        boolean flag = saveBatch(collect);
        long endTime = System.currentTimeMillis();
        log.info("使用的时间未", (endTime - startTime) / 1000);
        // 同步商品源接口
        return new AsyncResult<>(flag);
    }
//productSourcesList.stream().flatMap(Collection::stream).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ProductSource::getProductId))), ArrayList::new))
    public <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    public Boolean addProductSourceUrl(Long productId) {
        List<ProductSource> list = list(Wrappers.<ProductSource>lambdaQuery().eq(ProductSource::getProductId, productId));
        if(list.size() > 1) {
            throw new ServiceException("记录存在多条");
        }
        if(Func.isEmpty(list)) {
            throw new ServiceException("当前记录还未同步");
        }
        ProductSource productSource = list.get(0);
        String str = "https://pifa.pinduoduo.com/search";
        return update(Wrappers.<ProductSource>lambdaUpdate().set(ProductSource::getBaseUrl, str).eq(ProductSource::getProductId, productSource.getProductId()));
    }

    @Override
    public List<ProductSource> dataListSearch(List<Long> ids) {
        List<ProductSource> list = list(Wrappers.<ProductSource>lambdaQuery().in(ProductSource::getProductId, ids));
        return list;
    }
}
